﻿using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Sgr.Exceptions;
using Sgr.Oss;
using Sgr.Oss.Services;
using Sgr.Utilities;
using System;

namespace Microsoft.Extensions.DependencyInjection
{
    /// <summary>
    /// 依赖注入扩展
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 添加S3对象存储服务
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configureOptions">配置选项</param>
        /// <returns>服务集合</returns>
        public static IServiceCollection AddS3OssService(
            this IServiceCollection services,
            Action<S3Options>? configureOptions = null)
        {
            // 1. 配置验证器
            services.AddOptions<S3Options>()
                .BindConfiguration("Sgr:ThirdParty:S3")
                .Validate(ValidateOptionsInternal, "Invalid S3Options configuration");

            // 2. 用户自定义配置
            if (configureOptions != null)
                services.Configure(configureOptions);

            // 3. 后配置（设置默认值）
            services.PostConfigure<S3Options>(options =>
            {
                ConfigureDefaults(options);
                ValidateOptions(options); // 最终验证
            });

            // 4. 注册服务（替换已存在的IOssService实现）
            if (services.Any(f => f.ServiceType == typeof(IOssService)))
                services.Replace(ServiceDescriptor.Singleton<IOssService, S3OssService>());
            else
                services.AddSingleton<IOssService, S3OssService>();

            return services;
        }

        /// <summary>
        /// 验证所有配置项
        /// </summary>
        private static void ValidateOptions(S3Options options)
        {
            // EndPoint 验证
            if (string.IsNullOrWhiteSpace(options.EndPoint))
                throw new ArgumentException("EndPoint cannot be empty", nameof(options));
            if (!Uri.TryCreate(options.EndPoint, UriKind.Absolute, out _))
                throw new ArgumentException("EndPoint must be a valid absolute URL", nameof(options));

            // AccessKey 验证
            if (string.IsNullOrWhiteSpace(options.AccessKey))
                throw new BusinessException("未配置Oss S3服务访问密钥ID");

            // SecretKey 验证
            if (string.IsNullOrWhiteSpace(options.SecretKey))
                throw new BusinessException("未配置Oss S3服务私有访问密钥");

            // Region 验证
            if (string.IsNullOrWhiteSpace(options.Region))
                throw new ArgumentException("Region cannot be empty", nameof(options));

            // PublicBaseUrl 验证（如果提供）
            if (!string.IsNullOrEmpty(options.PublicBaseUrl) &&
                !Uri.TryCreate(options.PublicBaseUrl, UriKind.Absolute, out _))
                throw new ArgumentException("PublicBaseUrl must be a valid absolute URL", nameof(options));

            // DefaultPresignedUrlExpiryMinutes 验证
            if (options.DefaultPresignedUrlExpiryMinutes <= 0)
                throw new ArgumentException("DefaultPresignedUrlExpiryMinutes must be greater than 0", nameof(options));

            // TimeoutSeconds 验证
            if (options.TimeoutSeconds <= 0)
                throw new ArgumentException("TimeoutSeconds must be greater than 0", nameof(options));

            // MaxRetryCount 验证
            if (options.MaxRetryCount < 0)
                throw new ArgumentException("MaxRetryCount cannot be negative", nameof(options));

            // BucketCacheSeconds 验证
            if (options.BucketCacheSeconds < 0)
                throw new ArgumentException("BucketCacheSeconds cannot be negative", nameof(options));
        }

        /// <summary>
        /// 内部验证方法，用于Options验证器
        /// </summary>
        private static bool ValidateOptionsInternal(S3Options options)
        {
            try
            {
                ValidateOptions(options);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 配置默认值
        /// </summary>
        private static void ConfigureDefaults(S3Options options)
        {
            // AccessKey 处理
            if (string.IsNullOrEmpty(options.AccessKey))
            {
                options.AccessKey = EnvironmentHelper.GetEnvironmentVariable("SGR_OSS_ACCESSKEY") ??
                    throw new BusinessException("未配置Oss S3服务访问密钥ID");
            }

            // SecretKey 处理
            if (string.IsNullOrEmpty(options.SecretKey))
            {
                options.SecretKey = EnvironmentHelper.GetEnvironmentVariable("SGR_OSS_SECRETKEY") ??
                    throw new BusinessException("未配置Oss S3服务私有访问密钥");
            }

            // 设置其他默认值
            if (options.DefaultPresignedUrlExpiryMinutes <= 0)
                options.DefaultPresignedUrlExpiryMinutes = 60; // 默认1小时

            if (options.TimeoutSeconds <= 0)
                options.TimeoutSeconds = 30; // 默认30秒

            if (options.MaxRetryCount < 0)
                options.MaxRetryCount = 3; // 默认重试3次

            if (options.BucketCacheSeconds <= 0)
                options.BucketCacheSeconds = 300; // 默认5分钟
        }
    }
}